package com.zbbz.util.mybatis.buff;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;


public class BaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> {

    // 默认所有方法都注入关联数据，子类可重写此方法根据方法名称判断是否为此方法注入
    protected boolean shouldInject(String methodName) {
        return true;
    }

    // 获取关联配置（子类需重写此方法）
    protected <U, O> List<RelationConfig<U, O>> getRelationConfig() {
        return new ArrayList<>();
    }

    // 根据方法名判断是否注入关联数据
    private <R> R processResult(R result, String methodName) {
        if (shouldInject(methodName)) {
            if (result instanceof List) {
                return (R) MybatisPlusBuff.injectList((List<?>) result, getRelationConfig());
            } else {
                return (R) MybatisPlusBuff.injectOne(result, getRelationConfig());
            }
        }
        return result;
    }

    //--------------------------------------------------------------
    // 重写 MyBatis-Plus 的查询方法，按需注入关联数据
    //--------------------------------------------------------------

    @Override
    public T getById(Serializable id) {
        T entity = super.getById(id);
        return processResult(entity, "getById");
    }

    @Override
    public List<T> listByIds(Collection<? extends Serializable> idList) {
        List<T> list = super.listByIds(idList);
        return processResult(list, "listByIds");
    }

    @Override
    public List<T> listByMap(Map<String, Object> columnMap) {
        List<T> list = super.listByMap(columnMap);
        return processResult(list, "listByMap");
    }

    @Override
    public T getOne(Wrapper<T> queryWrapper) {
        T entity = super.getOne(queryWrapper);
        return processResult(entity, "getOne");
    }

    @Override
    public T getOne(Wrapper<T> queryWrapper, boolean throwEx) {
        T entity = super.getOne(queryWrapper, throwEx);
        return processResult(entity, "getOne");
    }

    @Override
    public <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
        V obj = super.getObj(queryWrapper, mapper);
        return processResult(obj, "getObj");
    }

    @Override
    public List<T> list(Wrapper<T> queryWrapper) {
        List<T> list = super.list(queryWrapper);
        return processResult(list, "list");
    }

    @Override
    public List<T> list() {
        List<T> list = super.list();
        return processResult(list, "list");
    }

    @Override
    public <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
        E p = super.page(page, queryWrapper);
        if (shouldInject("page")) {
            p.setRecords(MybatisPlusBuff.injectList(p.getRecords(), getRelationConfig()));
        }
        return p;
    }

    @Override
    public <E extends IPage<T>> E page(E page) {
        E p = super.page(page);
        if (shouldInject("page")) {
            p.setRecords(MybatisPlusBuff.injectList(p.getRecords(), getRelationConfig()));
        }
        return p;
    }
}